/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.support;

import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.AliasRegistry;

/**
 * Interface for registries that hold bean definitions, for example RootBeanDefinition
 * and ChildBeanDefinition instances. Typically implemented by BeanFactories that
 * internally work with the AbstractBeanDefinition hierarchy.
 *
 * <p>This is the only interface in Spring's bean factory packages that encapsulates
 * <i>registration</i> of bean definitions. The standard BeanFactory interfaces
 * only cover access to a <i>fully configured factory instance</i>.
 *
 * <p>Spring's bean definition readers expect to work on an implementation of this
 * interface. Known implementors within the Spring core are DefaultListableBeanFactory
 * and GenericApplicationContext.
 *
 * @author Juergen Hoeller
 * @since 26.11.2003
 * @see org.springframework.beans.factory.config.BeanDefinition
 * @see AbstractBeanDefinition
 * @see RootBeanDefinition
 * @see ChildBeanDefinition
 * @see DefaultListableBeanFactory
 * @see org.springframework.context.support.GenericApplicationContext
 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
 * @see PropertiesBeanDefinitionReader
 */

/**
 1. 作用总结
 BeanDefinitionRegistry 是 Spring 框架中用于注册和管理 Bean 定义的核心接口。
 它扩展了 AliasRegistry 接口，在提供别名管理功能的基础上，增加了对 Bean 定义的完整管理能力。
 该接口封装了 Spring 容器中 Bean 定义的注册、查询、删除等核心操作，是 Spring IoC 容器实现的基础。

 2 方法
	 void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)：注册一个新的 Bean 定义
	 void removeBeanDefinition(String beanName)：根据名称移除指定的 Bean 定义
	 BeanDefinition getBeanDefinition(String beanName)：根据名称获取 Bean 定义
	 boolean containsBeanDefinition(String beanName)：检查是否包含指定名称的 Bean 定义
	 String[] getBeanDefinitionNames()：获取所有已定义 Bean 的名称数组
	 int getBeanDefinitionCount()：获取已定义 Bean 的数量
	 boolean isBeanNameInUse(String beanName)：判断给定的 Bean 名称是否已被使用（包括本地 Bean 或别名）
 3. 与其他类和接口的关系
 AliasRegistry (父接口)
 ↑
 BeanDefinitionRegistry (当前接口)
 ↑
 DefaultListableBeanFactory (实现类)
 AbstractApplicationContext (实现类)
 ↑
 GenericApplicationContext (实现类)
	 主要关系说明：
		BeanDefinitionRegistry 继承了 AliasRegistry 接口，因此具备别名管理功能
	 主要实现类包括：
		 DefaultListableBeanFactory：Spring 默认的 BeanFactory 实现
		 GenericApplicationContext：通用应用上下文实现
	 被以下类使用：
		 XmlBeanDefinitionReader：XML 配置文件的 Bean 定义读取器
		 PropertiesBeanDefinitionReader：属性文件的 Bean 定义读取器
4. 应用场景
 Bean 定义注册：在 Spring 容器启动时，将配置文件或注解中的 Bean 定义注册到容器中
 动态 Bean 注册：在运行时动态向容器中注册新的 Bean 定义
 配置读取器支持：为各种 Bean 定义读取器（如 XML、Properties 等）提供统一的注册接口
 容器实现基础：作为 Spring IoC 容器实现的基础接口，支撑整个容器的 Bean 管理功能
 应用上下文支持：为各种应用上下文实现提供 Bean 定义管理能力


 */
public interface BeanDefinitionRegistry extends AliasRegistry {

	/**
	 * Register a new bean definition with this registry.
	 * Must support RootBeanDefinition and ChildBeanDefinition.
	 * @param beanName the name of the bean instance to register
	 * @param beanDefinition definition of the bean instance to register
	 * @throws BeanDefinitionStoreException if the BeanDefinition is invalid
	 * @throws BeanDefinitionOverrideException if there is already a BeanDefinition
	 * for the specified bean name and we are not allowed to override it
	 * @see GenericBeanDefinition
	 * @see RootBeanDefinition
	 * @see ChildBeanDefinition
	 */
	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException;

	/**
	 * Remove the BeanDefinition for the given name.
	 * @param beanName the name of the bean instance to register
	 * @throws NoSuchBeanDefinitionException if there is no such bean definition
	 */
	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	/**
	 * Return the BeanDefinition for the given bean name.
	 * @param beanName name of the bean to find a definition for
	 * @return the BeanDefinition for the given name (never {@code null})
	 * @throws NoSuchBeanDefinitionException if there is no such bean definition
	 */
	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	/**
	 * Check if this registry contains a bean definition with the given name.
	 * @param beanName the name of the bean to look for
	 * @return if this registry contains a bean definition with the given name
	 */
	boolean containsBeanDefinition(String beanName);

	/**
	 * Return the names of all beans defined in this registry.
	 * @return the names of all beans defined in this registry,
	 * or an empty array if none defined
	 */
	String[] getBeanDefinitionNames();

	/**
	 * Return the number of beans defined in the registry.
	 * @return the number of beans defined in the registry
	 */
	int getBeanDefinitionCount();

	/**
	 * Determine whether the given bean name is already in use within this registry,
	 * i.e. whether there is a local bean or alias registered under this name.
	 * @param beanName the name to check
	 * @return whether the given bean name is already in use
	 */
	boolean isBeanNameInUse(String beanName);

}
